package com.hrt.datasender.process.indentity;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.btcode.common.MyLog;
import com.btcode.exception.MsgException;
import com.btcode.log.ILog;
import com.btcode.reflect.AutoClassLoader;
import com.btcode.reflect.IClassFinder;
import com.btcode.reflect.IClassLoader;
import com.hrt.datasender.datadao.model.BcSendPlatformModel;
import com.hrt.datasender.datadao.service.BcSendPlatformService;

public final class IMessageIdentityLoader {

    private String basePacket = "com.hrt.datasender.process.indentity";

    private ILog log;

    private static volatile IMessageIdentityLoader instance;

    private List<IMessageIdentity> loaderProtocol = new ArrayList<>();

    private List<IMessageIdentity> existProtocols = new ArrayList<>();

    private HashMap<String, IMessageIdentity> protocolMap = new HashMap<>();

    private IMessageIdentityLoader() {
        log = MyLog.getInstance().getLogger(getClass().getName());
    }

    public static IMessageIdentityLoader getInstance() {
        if (instance == null) {
            synchronized (IMessageIdentityLoader.class) {
                if (instance == null) {
                    instance = new IMessageIdentityLoader();
                }
            }
        }
        return instance;
    }

    public IMessageIdentity getProtocolById(String protocolId) {
        loadAndGetProtocol();

        if (protocolMap.isEmpty()) {
            return null;
        }

        IMessageIdentity protocol = protocolMap.get(protocolId);

        return protocol;
    }

    /**
     * 加载配置好的策略
     *
     * @throws com.btcode.Execption.MessageException
     */
    public synchronized List<IMessageIdentity> loadAndGetProtocol() {

        if (loaderProtocol != null && loaderProtocol.size() > 0) {
            return loaderProtocol;
        }

        Set<String> protocolIds = getPlatformProtocolSet();

        for (String protocolId : protocolIds) {

            try {
                Class<?> objectClass = Class.forName(basePacket + "." + protocolId);

                Object obj = objectClass.newInstance();

                if (!(obj instanceof IMessageIdentity)) {
                    throw new MsgException("类:" + basePacket + "." + protocolId + ",没有实现" + basePacket + ".IProtocol接口",
                            null);
                }

                IMessageIdentity protocol = (IMessageIdentity) obj;

                loaderProtocol.add(protocol);
                protocolMap.put(protocol.getProtocolId(), protocol);

                log.info("策略：" + basePacket + "." + protocolId + "已加载");

            }
            catch (Exception e) {
                log.error("加载策略：" + basePacket + "." + protocolId + "失败", e);
            }
        }

        return loaderProtocol;
    }

    /**
     * 获取系统中存在的策略
     *
     * @param packetName
     * @return
     * @throws java.io.IOException
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    public synchronized List<IMessageIdentity> getExistprotocol()
            throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {

        if (existProtocols != null && existProtocols.size() > 0) {
            return existProtocols;
        }

        IClassFinder protocolFinder = new IMessageIdentityFinder();
        IClassLoader classLoader = new AutoClassLoader(protocolFinder);

        List<IMessageIdentity> protocolList = new ArrayList<>();
        List<Class<?>> myClasses = classLoader.loadClass(getClass(), basePacket);

        for (Class<?> myClass : myClasses) {
            Object instance = myClass.newInstance();
            protocolList.add((IMessageIdentity) instance);
        }

        existProtocols = protocolList;

        return protocolList;
    }

    /**
     * 获取配置好的，平台策略id集合
     *
     * @return
     */
    private Set<String> getPlatformProtocolSet() {

        List<BcSendPlatformModel> models = BcSendPlatformService.getInstance().getModelList();

        Set<String> platformSet = new HashSet<>();

        for (BcSendPlatformModel model : models) {
            platformSet.add(model.getTransportProtocolId());
        }

        return platformSet;
    }
}
